
class GameSnakeOnline : public Game
{
public:
    void Init();
    string Name()
    {
        return "snakeOnline";
    }
    void NewGame();
    void Step(ControllerState &controller) { StepHelper(controller); }
    ControllerState SimpleAI();

private:
    void MakeFrameSprites();
    void IncrementScore();
    void StepHelper(ControllerState &controller, bool setObservedInts=true);

    //
    // Useful functions
    //
    bool PassableOrSnakeHead(const SnakeTileEntry &entry) const;
    int EmptyRadius(const Vec2i &coord) const;

    inline int VertexFromCoord(int x, int y) const
    {
        return y * SnakeConstants::boardWidth + x;
    }
    inline int VertexFromCoord(const Vec2i &c) const
    {
        return c.y * SnakeConstants::boardWidth + c.x;
    }
    inline Vec2i CoordFromVertex(int v) const
    {
        return Vec2i(v % SnakeConstants::boardWidth, v / SnakeConstants::boardWidth);
    }


    //
    // Asset data
    //
    SnakeLevel _levelMap;

    //
    // Game state
    //
    Grid<SnakeTileEntry> _tiles;
    list<Vec2i> _snakeTiles;
    Vec2i _snakeDirection;
    int _maxSnakeLength;

    int _advanceFramesLeft;
    int _spawnFramesLeft;

    int _framesSinceGameReset;
    int _score;
    int _timeLeft;

    int _applesEaten;
    int _applesOnscreen;

    //
    // Sprite indices
    //
    int _spriteBlock;
    int _spriteBody;
    int _spriteHeadU;
    int _spriteHeadR;
    int _spriteHeadD;
    int _spriteHeadL;
    int _spriteApple;
    int _spriteGoldenApple;
    int _spriteBadApple;
};
